#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <complex>
#include <math.h>
#include <algorithm>
#include <opencv2/opencv.hpp>
//////////////////////////////////////////////////////////////////////////
using namespace cv;
//////////////////////////////////////////////////////////////////////////
# ifndef WAVELET
# define WAVELET
//////////////////////////////////////////////////////////////////////////
# define SYMMETRIC_EXTENSION     1
# define PERIODIC_EXTENSION      2
# define ZERO_PADDING_EXTENSION  3
//////////////////////////////////////////////////////////////////////////
# define SUBSAMPLING             1
# define NO_SUBSAMPLING          2
//////////////////////////////////////////////////////////////////////////
# define INTERPOLATION           1
# define NO_INTERPOLATION        2
//////////////////////////////////////////////////////////////////////////
# define DECOMPOSITION           1
# define RECONSTRUCTION          2
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
int signal_extension_d( double * original, int n, double * extended, int m, int type );
int signal_extension_r( double * original, int n, double * extended, int m, int type );
//////////////////////////////////////////////////////////////////////////
int convolution( double * data, int n, double * filter, int m, int type, double * result, int op );
//////////////////////////////////////////////////////////////////////////
int downsampling( double * data, int n, double * downdata );
int interpolation( double * data, int n, double * intpdata );
//////////////////////////////////////////////////////////////////////////
int wavelet_analysis
	( double * data, int n,		// original data
	double * Hi, int n_Hi,		// high pass filter
	double * Lo, int n_Lo,		// low pass filter
	double * approximation,		// approximation coefficients
	double * detail,			// detail coefficients
	int type,					// extension type
	int ifsubsample );			// determine if do sub-sampling
//////////////////////////////////////////////////////////////////////////
int wavelet_synthesis
	( double * approximation,	// approximation coefficients
	double * detail, int n,		// detail coefficients 
	double * Hi, int n_Hi,		// high pass filter
	double * Lo, int n_Lo,		// low pass filter
	double * data,				// synthesized data
	int type,					// extension type
	int ifinterpolation );		// determine if do interpolation
//////////////////////////////////////////////////////////////////////////
int multilevel_decomposition_1D
	( double * original,		// original signal
	int n,						// number of pointers, should be multiple of 2
	double * resultdata,		// decomposition data
	int nLevels,					// decomposition nLevels
	double * Hi, int n_Hi,		// high pass filter
	double * Lo, int n_Lo		// low pass filter
);				
//////////////////////////////////////////////////////////////////////////
int multilevel_reconstruction_1D
	( double * de_data,			// reconstructed signal
	int n,						// number of pointers, should be multiple of 2
	double * resultdata,		// reconstructed data
	int nLevels,					// reconstruct nLevels 
	double * Hi, int n_Hi,		// high pass filter
	double * Lo, int n_Lo		// low pass filter
);				 
//////////////////////////////////////////////////////////////////////////
int multilevel_decomposition_2D
	( double * image,			// original signal
	int width, int height,		// number of pointers, should be multiple of 2
	double * wavelet_data,			// decompositions data
	int nLevels,					// decomposition nLevels  
	double * Hi, int n_Hi,		// high pass filter
	double * Lo, int n_Lo		// low pass filter
);				
//////////////////////////////////////////////////////////////////////////
int multilevel_reconstruction_2D
	( double * wavelet_data,	// wavelet coefficients
	int width, int height,		// number of pointers, should be multiple of 2
	double * image,				// reconstructed data
	int nLevels,					// reconstruction nLevels
	double * Hi, int n_Hi,		// high pass filter
	double * Lo, int n_Lo		// low pass filter
 );				
//////////////////////////////////////////////////////////////////////////
int decomposition_2D_r
	( double * image,			// original signal
	int width, int height,		// number of pointers, should be multiple of 2
	double * Hi, int n_Hi,		// high pass filter
	double * Lo, int n_Lo,		// low pass filter
	double * approximation,		// decompositions data
	double * detail_h,			// horizontal
	double * detail_v,			// vertical 
	double * detail_d );		// diagonal 
//////////////////////////////////////////////////////////////////////////
int reconstruction_2D_r
	( double * approximation,	// wavelet coefficients
	double * detail_h,
	double * detail_v,
	double * detail_d,
	int width, int height,		// number of pointers, should be multiple of 2
	double * Hi, int n_Hi,		// high pass filter
	double * Lo, int n_Lo,		// low pass filter
	double * image );			// reconstructed data
# endif
//////////////////////////////////////////////////////////////////////////
Mat getForwardWaveletBasis(Mat img, int nLevels);
Mat getInverseWaveletBasis(Mat img, int nLevels);
//////////////////////////////////////////////////////////////////////////
Mat getForwardWaveletBasis2(Mat img, int nLevels);
Mat getInverseWaveletBasis2(Mat img, int nLevels);